package com.mustafa.payment.controller;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import com.mustafa.payment.dao.OrderMapper;
import com.mustafa.payment.model.OrderModel;
import com.mustafa.payment.util.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Controller
public class PayRunController {

    @Autowired
    private OrderMapper orderMapper;

    @Value("${payment.third.host}")
    private String host;

    @Value("${payment.third.pid}")
    private int pid;

    @Value("${payment.third.secret}")
    private String secret;

    @Value("${payment.third.returnUrl}")
    private String returnUrl;

    @Value("${payment.third.notifyUrl}")
    private String notifyUrl;

    @Value("${vip.product1}")
    private String money1;

    @Value("${vip.product2}")
    private String money2;

    @Value("${vip.product3}")
    private String money3;

    @Value("${vip.product4}")
    private String money4;

    @Value("${vip.product5}")
    private String money5;

    @Value("${vip.product6}")
    private String money6;

    @Value("${vip.product7}")
    private String money7;

    @Value("${vip.product8}")
    private String money8;

    @Value("${vip.days1}")
    private String days1;

    @Value("${vip.days2}")
    private String days2;

    @Value("${vip.days3}")
    private String days3;

    @Value("${vip.days4}")
    private String days4;

    @Value("${vip.days5}")
    private String days5;

    @Value("${vip.days6}")
    private String days6;

    @Value("${vip.days7}")
    private String days7;

    @Value("${vip.days8}")
    private String days8;

    @GetMapping("/pay/jump/{base64Str}")
    @ResponseBody
    public ResponseEntity<Void> payJump(@PathVariable("base64Str") String base64Str) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
        // 获取Base64解码器
        Base64.Decoder decoder = Base64.getUrlDecoder();

        // 使用解码器对编码的字符串进行解码
        byte[] decodedBytes = decoder.decode(base64Str);

        // 将解码后的字节转换为字符串
        String decodedString = new String(decodedBytes);

        String[] decodedArrary = decodedString.split("\\|\\|");
        String key = decodedArrary[0];
        String iv = decodedArrary[1];
        String content = decodedArrary[2];

        byte[] keyBytes = hexStringToByteArray(key);
        byte[] ivBytes = hexStringToByteArray(iv);

        // 将十六进制字符串转换为字节数组
        byte[] encryptedText = hexStringToByteArray(content);

        // 创建 SecretKeySpec 和 IvParameterSpec 对象
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

        // 初始化 Cipher 对象
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        // 进行解密
        byte[] decrypted = cipher.doFinal(encryptedText);

        // 打印解密后的结果
        content = new String(decrypted, StandardCharsets.UTF_8);
        String[] contentArr = content.split(":");
        String productName = contentArr[0];
        String payMethod = contentArr[1];
        String outTradeNo = contentArr[2];
        String param = contentArr[3];

        OrderModel orderModel = new OrderModel();
        orderModel.setOrderNo(outTradeNo);
        orderModel.setUid(param);
        orderModel.setProductName(productName);
        orderModel.setPayMethod(payMethod);
        orderModel.setEncryptionKey(key);
        orderModel.setEncryptionIv(iv);
        orderModel.setPayResult(0);
        this.orderMapper.createOrder(orderModel);

        String money = "1000";
        if (productName.equals("product1")) {
            money = money1;
        } else if (productName.equals("product2")) {
            money = money2;
        } else if (productName.equals("product3")) {
            money = money3;
        } else if (productName.equals("product4")) {
            money = money4;
        } else if (productName.equals("product5")) {
            money = money5;
        } else if (productName.equals("product6")) {
            money = money6;
        } else if (productName.equals("product7")) {
            money = money7;
        } else if (productName.equals("product8")) {
            money = money8;
        }

        String clientip = "192.168.1.100";
        String device = "jump";
        //封装好我们的请求参数
        String mdString = "clientip=" + clientip + "&device=" + device + "&money=" + money + "&name=" + productName + "&" +
                "notify_url=" + notifyUrl + "&out_trade_no=" + outTradeNo + "&param=" + param + "&pid=" + pid + "&return_url=" + returnUrl +
                "&type=" + payMethod + secret;
        //把我们的请求参数 md5加密
        String sign = MD5Util.GetMD5Code(mdString);

        Map<String, Object> map = new HashMap<>();
        map.put("pid", pid);
        map.put("type", payMethod);
        map.put("out_trade_no", outTradeNo);
        map.put("notify_url", notifyUrl);
        map.put("return_url", returnUrl);
        map.put("name", productName);
        map.put("money", money);
        map.put("clientip", clientip);
        map.put("device", device);
        map.put("param", param);
        map.put("sign", sign);
        map.put("sign_type", "MD5");

        String body = HttpUtil.post(host + "mapi.php", map);

        JSONObject jsonObject = new JSONObject(body);
        //拿到我们的返回的wx支付的url  转成二维码显示到前端
        String payUrl = (String) jsonObject.get("payurl");

        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(URI.create(payUrl)); // 设置Location头
        return new ResponseEntity<>(headers, HttpStatus.FOUND); // 302 Found

    }


    @RequestMapping("/pay/return")
    @ResponseBody
    public String payReturn(
            @RequestParam("pid") int pid,
            @RequestParam("trade_no") String tradeNo,
            @RequestParam("out_trade_no") String outTradeNo,
            @RequestParam("type") String type,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam("money") String money,
            @RequestParam("trade_status") String tradeStatus,
            @RequestParam("param") String param,
            @RequestParam("sign") String sign,
            @RequestParam("sign_type") String signType
    ) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        OrderModel order = this.queryOrder(outTradeNo);
        if (order != null && order.getPayResult() == 0 && tradeStatus.equals("TRADE_SUCCESS")) {
            this.orderMapper.setPayResult(outTradeNo);

            String productName = order.getProductName();
            String days = "1";
            if (productName.equals("product1")) {
                days = days1;
            } else if (productName.equals("product2")) {
                days = days2;
            } else if (productName.equals("product3")) {
                days = days3;
            } else if (productName.equals("product4")) {
                days = days4;
            } else if (productName.equals("product5")) {
                days = days5;
            } else if (productName.equals("product6")) {
                days = days6;
            } else if (productName.equals("product7")) {
                days = days7;
            } else if (productName.equals("product8")) {
                days = days8;
            }

            String key = order.getEncryptionKey();
            String iv = order.getEncryptionIv();
            String originString = productName + ":" + days + ":" + System.currentTimeMillis() + ":" + order.getPayMethod() + ":" + order.getOrderNo() + ":" + order.getUid();

            byte[] keyBytes = hexStringToByteArray(key);
            byte[] ivBytes = hexStringToByteArray(iv);
            // 创建 SecretKeySpec 和 IvParameterSpec 对象
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

            // 创建Cipher对象并初始化为加密模式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

            byte[] plainText = originString.getBytes();

            // 加密
            byte[] cipherText = cipher.doFinal(plainText);

            // 将密文转换为Base64编码以便于传输或存储
            String base64Content = Base64.getEncoder().encodeToString(cipherText);
            String htmlContent = "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n" +
                    "\n" +
                    "<h1>您的核销码</h1>\n" +
                    "<textarea style=\"width:100%\" rows=\"10\">" + base64Content + "</textarea>";
            return htmlContent;
        }

        return "success";
    }

    @RequestMapping("/pay/notify")
    @ResponseBody
    public String payNotify(
            @RequestParam("pid") int pid,
            @RequestParam("trade_no") String tradeNo,
            @RequestParam("out_trade_no") String outTradeNo,
            @RequestParam("type") String type,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam("money") String money,
            @RequestParam("trade_status") String tradeStatus,
            @RequestParam("param") String param,
            @RequestParam("sign") String sign,
            @RequestParam("sign_type") String signType
    ) {
        OrderModel order = this.queryOrder(outTradeNo);
        if (order != null && order.getPayResult() == 0 && tradeStatus.equals("TRADE_SUCCESS")) {
            this.orderMapper.setPayResult(outTradeNo);
        }

        return "success";
    }

    @GetMapping("/pay/query/{orderNo}")
    @ResponseBody
    public String outQueryOrder(@PathVariable("orderNo") String orderNo) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        OrderModel order = queryOrder(orderNo);
        if (order == null || order.getPayResult() == 0) {
            return "payment has not finished";
        }

        String productName = order.getProductName();
        String days = "1";
        if (productName.equals("product1")) {
            days = days1;
        } else if (productName.equals("product2")) {
            days = days2;
        } else if (productName.equals("product3")) {
            days = days3;
        } else if (productName.equals("product4")) {
            days = days4;
        } else if (productName.equals("product5")) {
            days = days5;
        } else if (productName.equals("product6")) {
            days = days6;
        } else if (productName.equals("product7")) {
            days = days7;
        } else if (productName.equals("product8")) {
            days = days8;
        }

        String key = order.getEncryptionKey();
        String iv = order.getEncryptionIv();
        String originString = productName + ":" + days + ":" + System.currentTimeMillis() + ":" + order.getPayMethod() + ":" + order.getOrderNo() + ":" + order.getUid();

        byte[] keyBytes = hexStringToByteArray(key);
        byte[] ivBytes = hexStringToByteArray(iv);
        // 创建 SecretKeySpec 和 IvParameterSpec 对象
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

        // 创建Cipher对象并初始化为加密模式
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        byte[] plainText = originString.getBytes();

        // 加密
        byte[] cipherText = cipher.doFinal(plainText);

        // 将密文转换为Base64编码以便于传输或存储
        String base64Content = Base64.getEncoder().encodeToString(cipherText);
        String htmlContent = "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n" +
                "\n" +
                "<h1>您的核销码</h1>\n" +
                "<textarea style=\"width:100%\" rows=\"10\">" + base64Content + "</textarea>";
        return htmlContent;
    }

    private OrderModel queryOrder(String orderNo) {
        OrderModel orderModel = orderMapper.getOrder(orderNo);
        return orderModel;
    }

    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }


}
